#include "../include/routemapdraw.h"
#include "../include/routedraw.h"
#include "../include/routemap.h"
#include "../include/route.h"

using namespace Cairo;
using namespace std;
using namespace vectorMap;
namespace drawables{
namespace vectorMap{

RouteMapDraw::RouteMapDraw(RouteMap* map)
{
    //ctor
    this->map = map;
    show_all();
//     #ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
      //Connect the signal handler if it isn't already a virtual method override:      this->sign
      signal_expose_event().connect(sigc::mem_fun(*this, &RouteMapDraw::on_draw), false);
 //     #endif //GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED

    nodeColors.push_back({1.0, 0.0, 0.0});
    nodeColors.push_back({0.0, 1.0, 0.0});
    nodeColors.push_back({0.0, 0.0, 1.0});
    nodeColors.push_back({1.0, 0.0, 1.0});
    nodeColors.push_back({1.0, 1.0, 0.0});
    nodeColors.push_back({0.0, 1.0, 1.0});
    nodeColors.push_back({1.0, 1.0, 1.0});

    redrawBackgroundMap();
	Route* testroute = new Route(&map->nodes[1]);
	*testroute << map->nodes[6];
	addDrawable(new RouteDraw(testroute));
	addDrawable(new RouteDraw(map->route(1, 6), {0,1,0}) );
	addDrawable(new RouteDraw(map->route(90, 6), {0,1,1}) );
	addDrawable(new RouteDraw(map->route(90, 200), {1,1,0}) );

}



RouteMapDraw::~RouteMapDraw()
{
    //dtor
}

bool RouteMapDraw::redrawBackgroundMap(){
//todo make it draw on the surface
    Mutex::Lock lock(mutex);
//    Glib::RefPtr<Gdk::Window> window = get_window( );
    Allocation allocation = get_allocation();
    const int width = allocation.get_width();
    const int height = allocation.get_height();

//    if(mapBackground)
  //      delete mapBackground;
    mapBackground = ImageSurface::create(FORMAT_ARGB32, width, height);
    Cairo::RefPtr<Cairo::Context> cr = Context::create(mapBackground);

    cr->set_line_cap(LINE_CAP_ROUND);
    cr->set_line_width(100);


    hborder = ((double) (map->right  - map->left)) *0.05;
    vborder = ((double) (map->bottom - map->top ))*0.05 ;

    cr->scale(
              ((double) width )/ ((double) (map->right  - map->left + (2.0*hborder) )),
              ((double) height)/ ((double) (map->bottom - map->top + (2.0*vborder)  ))
               );


   cr->translate( ((double)-map->left) + hborder, ((double)-map->top) + vborder);

        cr->set_source_rgb(0, 0, 0);
        cr->paint();
//*/
    beforeDraw(cr);
    for(unsigned i=0; i<map->nodes.size(); i++){
//        cr->paint();
        cr->save();
        cr->move_to(
                    map->nodes[i].place->x,
                    map->nodes[i].place->y
                    );

        for(int j=0; j<map->nodes[i].outgoing.size(); j++){
            cr->save();
            drawPath(&map->nodes[i], map->nodes[i].outgoing[j], cr);
            cr->restore();
        }
    }
    for(unsigned i=0; i<map->nodes.size(); i++){
        cr->save();
        drawNode(&map->nodes[i], cr);
        cr->restore();
    }
    mapBackground->flush();
	//uncomment for debug: save the map image
    mapBackground->write_to_png("test.png");
}

bool RouteMapDraw::on_draw(GdkEventExpose* gee){// (const ::Cairo::RefPtr< Context >& cr){d
    Glib::RefPtr<Gdk::Window> window = get_window();
    Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
    Allocation allocation = get_allocation();
    const int width = allocation.get_width();
    const int height = allocation.get_height();

    if (mapBackground->get_width()!=width || mapBackground->get_height()!=height)
        redrawBackgroundMap();
	cr->set_source(mapBackground, 0, 0);
    cr->paint();


 cr->scale(
              ((double) width )/ ((double) (map->right  - map->left + (2.0*hborder) )),
              ((double) height)/ ((double) (map->bottom - map->top + (2.0*vborder)  ))
               );

   cr->translate( ((double)-map->left) + hborder, ((double)-map->top) + vborder);


	for(vector<drawables::vectorMap::MapDrawable*>::iterator iter = thingsToDraw.begin(); iter<thingsToDraw.end(); iter++){
		(*iter)->draw(cr);
	}

  //  afterDraw(cr);
    return true;
}
    void RouteMapDraw::drawNode(Node* node, Cairo::RefPtr<Cairo::Context> cr){
        cr->set_source_rgba(nodeColors.front().r, nodeColors.front().g, nodeColors.front().b, 0.5);
        cr->set_line_width(900);
        cr->arc(node->place->x, node->place->y, 3000, 0.0, 2.0 * M_PI); // full circle



        cr->fill_preserve();
        cr->set_source_rgba(nodeColors.front().r, nodeColors.front().g, nodeColors.front().b, 1);
        cr->stroke();

    }



    void RouteMapDraw::drawPath(Node* node, ::vectorMap::Path* path, Cairo::RefPtr<Cairo::Context> cr){
        cr->save();
        cr->set_source_rgb(1, 0, 0);
        cr->line_to(
                    path->to->place->x,
                    path->to->place->y
                    );
        cr->restore();
    }

void RouteMapDraw::addDrawable(MapDrawable* drawable)
{
	if (find(thingsToDraw.begin(), thingsToDraw.end(), drawable) == thingsToDraw.end())
		thingsToDraw.push_back(drawable);
}

void MapDrawable::draw(Cairo::RefPtr<Cairo::Context> cr)
{
	cr->set_source_rgba(1, 1, 1, 0.5);

    cr->arc(subject->place->x, subject->place->y, 10000, 0.0, 2.0 * M_PI); // full circle
    cr->fill_preserve();
    cr->set_line_width(5000);
	cr->set_source_rgba(1, 1, 1, 1);
    cr->stroke();
}


}//namespace
}//řnamespace
